﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bank
{
    /// <summary>
    /// Класс "Банк"
    /// </summary>
    class Bank
    {
		// Счётчик банков (используется при генерации ID счёта)
		protected static int _id = 0;
		private string _name;

		// типы счётов при переводе денег
		enum AccTransferType { Source, Destination};

		/// <summary>
		/// список счетов банка
		/// </summary>
		public List<Account> Accounts;
		/// <summary>
		/// список клиентов банка
		/// </summary>
		public List<Client> Clients;

		/// <summary>
		/// свойство Имя банка
		/// </summary>
		public string Name
		{
			get { return _name; }
		}

		/// <summary>
		/// свойство ID банка
		/// </summary>
		public int ID
		{
			get
			{
				return _id;
			}
		}

		/// <summary>
		/// Найти счёт в массиве счетов
		/// </summary>
		/// <param name="AccID">ID счёта</param>
		/// <returns></returns>
		public Account FindAcc(string AccID)
		{
			bool exist = false;
			int i;
			// найдём в массиве счетов заданный
			for (i = 0; i < Accounts.Count; i++)
			{
				if (Accounts[i].ID == AccID)
				{
					exist = true;
					break;
				}
			}
			// Выведем сообщение на консоль
			if (!exist)
			{
				Message("Счёт не найден");
				return null;
			}
			else
			{
				return Accounts[i];
			}

		}

		/// <summary>
		/// Найти клиента
		/// </summary>
		/// <param name="ClientID">ID клиента</param>
		/// <returns>Клиент</returns>
		public Client FindClient(string ClientID)
		{
			bool exist = false;
			int i;
			for (i = 0; i < Clients.Count; i++)
			{
				if (Clients[i].ID == ClientID)
				{
					exist = true;
					break;
				}
			}
			if (!exist)
			{
				Message("Клиент не найден");
				return null;
			}
			else
			{
				return Clients[i];
			}

		}

        /// <summary>
		/// Метод: добавить деньги на счёт
        /// </summary>
        /// <param name="Acc">Счёт</param>
        /// <param name="Summ">Сумма</param>
        public void AddBalance(Account Acc, double Summ) { return; }

		/// <summary>
		/// Метод: удалить деньги со счёта
		/// </summary>
		/// <param name="Acc">Счёт</param>
		/// <param name="Summ">Сумма</param>
        public void WithDraw(Account Acc, double Summ) { return; }

		/// <summary>
		/// Метод: добавить нового клиента
		/// </summary>
		/// <returns>Клиент</returns>
        public Client CreateClient() 
        {
			Client newClient = new Client(this);
            Clients.Add(newClient);
			Message("Клиент №"+newClient.ID+" успешно создан в банке "+ this.Name + "(№ банка: "+this.ID.ToString("D3")+")");
            return newClient; 
        }

		/// <summary>
		/// Метод: создать новый счёт в банке
		/// </summary>
		/// <param name="client"></param>
		/// <returns>Счёт</returns>
		public Account CreateAccount(Client client)
		{
			this.Message("Дата закрытия счёта:");
			DateTime DateExpire = this.GetDateTime();

			this.Message("Введите первоначальный баланс:");
			double initBalance = this.GetDouble();
			// Создаём счёт вызвав конструктор
			Account newAccount = new Account(this, client, DateExpire, initBalance);
			// Добавим счёт в список счетов банка
			Accounts.Add(newAccount);
			Message("Счёт №" + newAccount.ID + " успешно создан в банке " + this.Name 
					+ "(№ банка: " + this.ID.ToString("D3") + ")");
			// возвратим новый счёт
			return newAccount;
		}

		/// <summary>
		/// Метод: вывести информацию о последнем аккаунте
		/// </summary>
		public void ShowAccountInfo()
		{
			if (this.Accounts.Count > 0)
				this.Accounts.Last().ToString();
			else
				Message("Нет счетов в банке");
		}

		/// <summary>
		/// Метод: вывести информацию о конкретном аккаунте
		/// </summary>
		/// <param name="AccountID">Счёт</param>
		public void ShowAccountInfo(string AccountID)
		{
			bool AccountExist = false;
			foreach (Account account in this.Accounts)
			{
				if (account.ID == AccountID)
				{
					account.ToString();
					AccountExist = true;
				}
				if (!AccountExist)
					Console.WriteLine("Такой счёт не существует");
			}
		}

		/// <summary>
		/// Метод: инициализация банка
		/// </summary>
		private void Init()
		{
			// создаём список для хранения клиентов
			Clients = new List<Client>();
			// создаём список для хранения счетов
			Accounts = new List<Account>();
			// установим ID банка
			_id++;
		}
		
		// конструктор банка по умолчанию
		public Bank()
		{
			this._name = "NoName";
			Init();
		}

		/// <summary>
		/// Метод: перевод денег с одного счёта на другой
		/// </summary>
		/// <returns></returns>
		public bool Transfer()
		{
			Message("Введите сумму денег для перевода: ");
			double Amount = GetDouble();

			// запросим номер счёта-источника
			string strSourceAccID = GetAccountID(AccTransferType.Source);
			// поиск счёта в списке счетов банка
			Account SourceAcc = FindAcc(strSourceAccID);

			// если счёт не найден - перевод денег невозможен
			if (SourceAcc == null)
			{

				Message("Счёт-источник не найден");
				return false;
				//throw new Exception("Счёт-источник не найден");
			}

			// запросим номер счёта-приёмника
			string strDestinationAccID = GetAccountID(AccTransferType.Destination);
			// поиск счёта в списке счетов банка
			Account DestinationAcc = FindAcc(strDestinationAccID);

			// если счёт не найден - перевод денег невозможен
			if (DestinationAcc == null)
			{
				Message("Счёт-источник не найден");
				return false;
				//throw new Exception("Счёт-приёмник не найден");
			}

			// Если операция по снятию денег со счёта прошла успешно
			if (SourceAcc.MoneyDec(Amount))
			{
				// добавим снятые деньги на счёт-приёмник
				DestinationAcc.MoneyInc(Amount);
				return true;
			}
			else
				return false;

			/*
			// Если оперируем счетами
			if (this.Accounts.Contains(SourceAcc) && this.Accounts.Contains(DestinationAcc))
			{
				this.Accounts.Find(
					delegate(Account acc)
					{
						return acc.ID == SourceAcc.ID;
					}
				).MoneyDec(Amount);

				this.Accounts.Find(
					delegate(Account acc)
					{
						return acc.ID == DestinationAcc.ID;
					}
				).MoneyInc(Amount);
				return true;
			}
			*/
		}

		/// <summary>
		/// конструктор банка с именем
		/// </summary>
		/// <param name="Name">Имя счёта</param>
		public Bank(string Name)
		{
			Init();
			this._name = Name;
		}

		/// <summary>
		/// Вывод сообщения в консоль
		/// </summary>
		/// <param name="msg"></param>
		void Message(string msg)
		{
			Console.WriteLine(msg);
		}

		/// <summary>
		/// Запросить номер счёта для перевода денег
		/// </summary>
		/// <param name="AccTT">Тип счёта при переводе</param>
		/// <returns>ID счёта</returns>
		string GetAccountID(AccTransferType AccTT)
		{
			switch (AccTT)
			{
				case AccTransferType.Source:
					Console.WriteLine("Введите ID счёта-источника: ");
					break;
				case AccTransferType.Destination:
					Console.WriteLine("Введите ID счёта-назначения: ");
					break;
			}
			
			return Console.ReadLine();
		}

		/// <summary>
		/// Ввод строки с консоли
		/// </summary>
		/// <returns></returns>
		string GetString()
		{
			return Console.ReadLine();
		}

		/// <summary>
		/// Ввод дробного числа c консоли
		/// </summary>
		/// <returns></returns>
		double GetDouble()
		{			
			return double.Parse(Console.ReadLine());
		}

		/// <summary>
		/// Ввод даты c консоли
		/// </summary>
		/// <returns></returns>
		DateTime GetDateTime()
		{
			return DateTime.Parse(Console.ReadLine());
		}

    }
}
